package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.to.SkuReductionTO;
import com.atguigu.common.to.SpuBoundsTO;
import com.atguigu.common.to.es.SkuEsModel;
import com.atguigu.common.utils.Constant;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.dao.SpuImagesDao;
import com.atguigu.gulimall.product.dao.SpuInfoDescDao;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.feign.SearchFeignService;
import com.atguigu.gulimall.product.feign.WareFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private AttrService attrService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private SearchFeignService searchFeignService;





    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveSpuInfo(SpuSaveVO spuInfo) {
        //1.保存spu 商品基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuInfo,spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.save(spuInfoEntity);
        Long spuId = spuInfoEntity.getId();


        //2.保存Spu的描述 pms_spu_info_desc
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        //todo entity id 不为空？
        spuInfoDescEntity.setSpuId(spuId);
        spuInfoDescEntity.setDecript(String.join(",",spuInfo.getDecript()));
        spuInfoDescService.save(spuInfoDescEntity);
//        spuInfoDescDao.insert(spuInfoDescEntity);

        //3.保存spu的图片集 pms_spu_images
        spuImagesService.saveImages(spuId,spuInfo.getImages());

        //4.保存spu的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuInfo.getBaseAttrs();
        productAttrValueService.saveBaseAttrs(spuId,baseAttrs);

        //5.保存spu积分信息 gulimall_sms -> sms_spu_bounds
        Bounds bounds = spuInfo.getBounds();
        SpuBoundsTO spuBoundsTO = new SpuBoundsTO();
        BeanUtils.copyProperties(bounds,spuBoundsTO);
        spuBoundsTO.setSpuId(spuId);
        R boundsResp = couponFeignService.saveSpuBounds(spuBoundsTO);
        if(boundsResp.getCode()!=0){
            log.error("远程保存spu积分信息失败");
        }


        //6.保存当前spu对应的所有sku信息
        List<Skus> skus = spuInfo.getSkus();
        if(skus!=null&&skus.size()>0){
            skus.forEach((item)->{
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                //5.1 sku基本信息 pms_sku_info
                //skuName;price;skuTitle;skuSubtitle;
                BeanUtils.copyProperties(item,skuInfoEntity);
                skuInfoEntity.setSpuId(spuId);
                skuInfoEntity.setCatalogId(spuInfo.getCatalogId());
                skuInfoEntity.setBrandId(spuInfo.getBrandId());
                skuInfoEntity.setSaleCount(0L);
                //5.2 sku图片信息 pms_sku_images
                String defaultImg="";
                for(Images img:item.getImages()){
                    if(!StringUtils.isEmpty(img.getImgUrl())){
                        if(img.getDefaultImg()==1){
                            defaultImg=img.getImgUrl();
                        }
                    }
                }
                if(defaultImg!=null){
                    skuInfoEntity.setSkuDefaultImg(defaultImg);
                }

                //todo desc??
                skuInfoService.save(skuInfoEntity);
                Long skuId = skuInfoEntity.getSkuId();

                //
                List<SkuImagesEntity> imagesCollect = item.getImages().stream().map((img) -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuId);
                    BeanUtils.copyProperties(img, skuImagesEntity);
                    return skuImagesEntity;

                }).filter(entity->{
                    //返回true 需要； false 过滤
                    String url =entity.getImgUrl();
                    return !StringUtils.isEmpty(url)&&!"".equals(url);
                }).collect(Collectors.toList());
                skuImagesService.saveBatch(imagesCollect);



                //5.3 sku销售属性信息 pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                skuSaleAttrValueService.saveSaleAttrs(skuId,attrs);
                //5.4 sku的优惠、满减等信息 gulimall_sms-> sms_sku_ladder / sms_sku_full_reduction / sms_member_price
                SkuReductionTO skuReductionTO = new SkuReductionTO();
                skuReductionTO.setSkuId(skuId);
                BeanUtils.copyProperties(item,skuReductionTO);
                R reductionResp = couponFeignService.saveSkuReduction(skuReductionTO);
                if(reductionResp.getCode()!=0){
                    log.error("远程保存sku满减信息失败");
                }



            });
        }






    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        String status = (String) params.get("status");
        String brandId = (String) params.get("brandId");
        String catelogId = (String) params.get("catelogId");
        if(!StringUtils.isEmpty(key)){
            wrapper.and(w->{
                w.eq("spu_name",key).or().like("spu_name",key);
            });
        }
        if(!StringUtils.isEmpty(status)){
            wrapper.and(w->{
                w.eq("publish_status",status);
            });
        }
        if(!StringUtils.isEmpty(brandId)){
            if(Long.parseLong(brandId)>0){
                wrapper.and(w->{
                    w.eq("brand_id",brandId);
                });
            }
        }
        if(!StringUtils.isEmpty(catelogId)){
            if(Long.parseLong(catelogId)>0){
                wrapper.and(w->{
                    w.eq("catalog_id",catelogId);
                });
            }

        }
        IPage page = this.page(new Query<SpuInfoEntity>().getPage(params), wrapper);
        return new PageUtils(page);

    }

    @Override
    @Transactional
    public void up(Long spuId) {
        List<SkuEsModel> upProducts = new ArrayList<>();
        //组装需要的数据
        //1.查出spuId对应的所有sku信息
        //TODO 4. 查询sku所有的 可以被用来检索的 规格属性attrs
        //所有的sku共享一个spu的规格属性 只用查一遍
        List<ProductAttrValueEntity> baseAttrs = productAttrValueService.baseAttrListForSpu(spuId);

        List<Long> attrIds = baseAttrs.stream().map(baseAttr -> {
            return baseAttr.getAttrId();
        }).collect(Collectors.toList());

        List<Long> searchAttrIds =  attrService.selectSearchAttrIds(attrIds);
        Set<Long> idSet = new HashSet<>(searchAttrIds);


        List<SkuEsModel.Attrs> attrs = baseAttrs.stream().filter(baseAttr -> {
            return idSet.contains(baseAttr.getAttrId());
        }).map(item -> {
            SkuEsModel.Attrs attrItem = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item, attrItem);
            return attrItem;
        }).collect(Collectors.toList());


        List<SkuInfoEntity> skus =  skuInfoService.getSkusBySpuId(spuId);
        List<Long> skuIds = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());


        //TODO 1. 发送远程调用，库存系统查询是否有库存
        Map<Long, Boolean> stockMap = null;
        try {
            R skusHasStockResponse = wareFeignService.getSkusHasStock(skuIds);
            List<SkuHasStockVo> hasStockVOs = (List<SkuHasStockVo>) skusHasStockResponse.get("data");
            stockMap = hasStockVOs.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, SkuHasStockVo::getHasStock));

        }catch (Exception e){
            log.error("库存服务查询异常:原因{}",e);
        }finally {

        }



        //封装每个skuEsModel
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> collect = skus.stream().map(skuInfoEntity -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, skuEsModel);
            Long brandId = skuInfoEntity.getBrandId();
            Long catalogId = skuInfoEntity.getCatalogId();
            skuEsModel.setSkuPrice(skuInfoEntity.getPrice());
            skuEsModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());
            //设置库存信息 hasStock
            if(finalStockMap ==null){
                skuEsModel.setHasStock(true);
            }else{
                skuEsModel.setHasStock(finalStockMap.get(skuInfoEntity.getSkuId()));
            }
            //TODO 2. 热度评分，hotScore 单独处理
            skuEsModel.setHotScore(0L);
            //brandName brandImg catalogName
            BrandEntity brandEntity = brandService.getById(brandId);
            CategoryEntity catalogEntity = categoryService.getById(catalogId);
            skuEsModel.setBrandImg(brandEntity.getLogo());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setCatalogName(catalogEntity.getName());
            //设置检索属性
            skuEsModel.setAttrs(attrs);


            return skuEsModel;
        }).collect(Collectors.toList());
        //TODO 5 将数据发给es进行保存
        R r = searchFeignService.productStatusUp(collect);
        if (r.getCode()==0) {
            //远程调用成功
            //TODO 6 改变spu上架状态
            this.baseMapper.updateSpuStatus(spuId,ProductConstant.StatusEnum.SPU_UP.getCode());
        }else{
            //远程调用失败
            //TODO 重复调用？接口幂等性？重试机制？
            //feign调用流程
            /**
             * 1.构造请求数据，对象转为json
             * 2.发送请求进行执行（执行成功会解码响应数据）
             *      executeAndDecode(template)
             * 3.执行请求会有重试机制 默认关闭 Retryer重试器接口 有多种实现，传入不同的最大重试次数
             *         while(true){
             *             try{
             *                 return executeAndDecode(template)
             *             }catch(){
             *                  try{
             *                      retryer.conntinueOrPropagate(e) //继续或传播
             *                      catch(){throw ex};
             *                      continue;
             *                  }
             *
             *
             *             }

             *
             *
             *         }
             */

        }


    }

}